home *** CD-ROM | disk | FTP | other *** search
/ Libris Britannia 4 / science library(b).zip / science library(b) / CUGUK / COMMS / C011.ZIP / IBMTTY.C < prev    next >
Text File  |  1990-01-19  |  17KB  |  659 lines

  1.  
  2. /********************************************************************
  3.  * C Users Group (U.K) C Source Code Library File CUGLIB.011        *
  4.  * Inquiries to: M. Houston, 36 Whetstone Clo. Farquhar Rd.         *
  5.  * Edgbaston, Birmingham B15 2QN ENGLAND                *
  6.  ********************************************************************
  7.  * File name: ibmtty.c
  8.  * Program name: ibmtty
  9.  * Source of file: The Public Domain Software Library.
  10.  * Purpose: A terminal emulation program.
  11.  * Changes: <who what when & why major changes have been made>      
  12.  ********************************************************************/
  13.  
  14. /*                          *** ibmtty.c ***                         */
  15. /*                                                                   */
  16. /* IBM-PC microsoft "C" under PC-DOS                                 */
  17. /*                                                                   */
  18. /* Terminal emulation program with file upload and download capabili-*/
  19. /* ties.  Optimized to communicate with a DEC VAX 11/780.            */
  20. /*                                                                   */
  21. /* Written by L. Cuthbertson, April 1984.                            */
  22. /*                                                                   */
  23. /*********************************************************************/
  24. /*                                                                   */
  25.  
  26. #include <stdio.h>
  27.  
  28. #define TRUE 1
  29. #define FALSE 0
  30. #define XON '\021'
  31. #define XOFF '\023'
  32. #define ESC '\033'
  33. #define CONZ '\032'
  34. #define DEL '\177'
  35.  
  36. #define LCR 0x3FB    /* 8250 line control register */
  37. #define DLL 0x3F8    /* 8250 least significant divisor latch */
  38. #define DLM 0x3F9    /* 8250 most significant divisor latch */
  39. #define LSR 0x3FD    /* 8250 line status register */
  40. #define IIR 0x3FA    /* 8250 interrupt identification register */
  41. #define IER 0x3F9    /* 8250 interrupt enable register */
  42. #define MCR 0x3FC    /* 8250 modem control register */
  43. #define MSR 0x3FE    /* 8250 modem status register */
  44. #define RBR 0x3F8    /* 8250 receiver buffer register */
  45. #define THR 0x3F8    /* 8250 transmitter holding register */
  46.  
  47. char *lcr=(char*)LCR, *dll=(char*)DLL, *dlm=(char*)DLM;
  48. char *lsr=(char*)LSR, *iir=(char*)IIR, *ier=(char*)IER;
  49. char *mcr=(char*)MCR, *msr=(char*)MSR, *rbr=(char*)RBR;
  50. char *thr=(char*)THR;
  51.  
  52. struct buf {
  53.     char *fbuf;
  54.     char *wbuf,*rbuf;
  55.     char *lbuf;
  56. };
  57.  
  58. struct buf mem;            /* file receiption/transmission buff */
  59.  
  60. char combuf[64];        /* transmission buffer */
  61. struct buf com;
  62.  
  63. char crtbuf[512];        /* receiption buffer */
  64. struct buf crt;
  65.  
  66. char outfil[13];        /* transmit file name */
  67. FILE *outchan;
  68.  
  69. char infil[13];            /* receive file name */
  70. FILE *inchan;
  71.  
  72. char lecho = FALSE;
  73. char gotxoff = FALSE;
  74. char sendxoff = FALSE;
  75. char sentxoff = FALSE;
  76.  
  77. /*********************************************************************/
  78. /*                                                                   */
  79. main(argc,argv)
  80. int argc;
  81. char *argv[];
  82. {
  83.     char *malloc();
  84.     int iret,port;
  85.     unsigned u;
  86.  
  87.     /* initialize file receiption/transmission */
  88.     inchan = FALSE;
  89.     outchan = FALSE;
  90.  
  91.     /* set up buffer structures */
  92.     com.fbuf = com.wbuf = com.rbuf = &combuf[0];
  93.     com.lbuf = &combuf[0] + sizeof(combuf) - 1;
  94.     crt.fbuf = crt.wbuf = crt.rbuf = &crtbuf[0];
  95.     crt.lbuf = &crtbuf[0] + sizeof(crtbuf) - 1;
  96.  
  97.     /* allocate as much memory as possible to file buffer */
  98.     for (u=65023;;u -= 512) {
  99.         if (u < (512+(5*_BUFSIZ))) {
  100.             writes("\r\n\007*** not enough memory available ***");
  101.             exit();
  102.         }
  103.         mem.fbuf = malloc(u);
  104.         if (mem.fbuf != 0) {
  105.             free(mem.fbuf);
  106.             u -= 5*_BUFSIZ;
  107.             mem.fbuf = malloc(u);
  108.             break;
  109.         }
  110.     }
  111.  
  112.     mem.wbuf = mem.rbuf = mem.fbuf;
  113.     mem.lbuf = mem.fbuf + u - 1;
  114.  
  115.     /* determine communications port to use */
  116.     if (argc > 1) {
  117.         sscanf(argv[1],"%d",&port);
  118.         port--;
  119.         if ((port < 0) || (port > 1)) {
  120.             writes("\r\n\007*** invalid communications port - enter 1 or 2 ***");
  121.             exit();
  122.         }
  123.     } else {
  124.         port = 0;
  125.     }
  126.  
  127.     /* adjust port addresses if neccessary */
  128.     if (port == 1) {
  129.         lcr -= 0x100;
  130.         dll -= 0x100;
  131.         dlm -= 0x100;
  132.         lsr -= 0x100;
  133.         iir -= 0x100;
  134.         ier -= 0x100;
  135.         mcr -= 0x100;
  136.         msr -= 0x100;
  137.         rbr -= 0x100;
  138.         thr -= 0x100;
  139.     }
  140.  
  141.     /* initialize 8250  - use DOS "MODE" command */
  142.     outp(mcr,3);        /* send DTR and RTS */
  143.     pause(1.);
  144.  
  145.     /* check for carrier */
  146.     if ((inp(msr)&48) != 48) {
  147.         writes("\r\n\007*** carrier not detected - please check your connections ***");
  148.         exit();
  149.     }
  150.  
  151.     /* courtesy message */
  152.     cursor(25,1);
  153.     writes("\r\n*** you are now connected ***\r\n");
  154.  
  155.     /* polling loop */
  156.     for (;;) {
  157.  
  158.         /* check communications port for reception of data */
  159.         if ((readcomm()) != 0)
  160.             ;
  161.  
  162.         /* check if screen output needed */
  163.         if ((wrtscr()) != 0)
  164.             ;
  165.  
  166.         /* check communications port for receiption of data */
  167.         if ((readcomm()) != 0)
  168.             ;
  169.  
  170.         /* write characters to comm port for transmission */
  171.         if ((wrtcomm()) != 0)
  172.             ;
  173.  
  174.         /* check communications port for receiption of data */
  175.         if ((readcomm()) != 0)
  176.             ;
  177.  
  178.         /* check for screen output */
  179.         if ((wrtscr()) != 0)
  180.             ;
  181.  
  182.         /* check communications port for receiption of data */
  183.         if ((readcomm()) != 0)
  184.             ;
  185.  
  186.         /* check for keyboard entry */
  187.         if ((readkey()) != 0)
  188.             ;
  189.  
  190.     }
  191. }
  192.  
  193. /*********************************************************************/
  194. /* Check the comm port for receiption of data and puts recieved data */
  195. /* into buffers.  Returns a -1 if error detected, 0 if no data, or   */
  196. /* the character received.                                           */
  197. /*                                                                   */
  198. int readcomm()
  199. {
  200.     static char oldc = NULL;
  201.     static char c;
  202.     static int iret;
  203.  
  204.     /* check comm port for data receiption */
  205.     iret = inp(lsr);
  206.     if ((iret&1) != 0) {
  207.  
  208.         /* ignore data overrun errors */
  209.         /* expect to loose padd characters at high baud rate */
  210.         if ((iret&2) != 0) {
  211.             ;
  212.  
  213.         /* framing or parity error */
  214.         } else if ((iret&12) != 0) {
  215.             writes("\007*** data reception error ***");
  216.             return(-1);
  217.  
  218.         /* break currenly being sent */
  219.         } else if ((iret&16) != 0) {
  220.             return(0);    /* break detect */
  221.         }
  222.  
  223.         /* read character */
  224.         c = inp(rbr)&127;
  225.  
  226.         /* process character */
  227.         if (c == XOFF) {
  228.             gotxoff = TRUE;
  229.         } else if (c == XON) {
  230.             gotxoff = FALSE;
  231.         } else if (c != NULL) {
  232.  
  233.             /* prevent CR CR LF line endings */
  234.             if ((c != '\r') || (oldc != '\r')) {
  235.  
  236.                 /* store character in receiption buffer */
  237.                 if ((putbuf(&crt,c)) == (-1)) {
  238.                     writes("\007*** screen buffer overflow ***");
  239.                     return(-1);
  240.                 }
  241.  
  242.                 /* store character if file receiption buffer */
  243.                 if (inchan) {
  244.                     if ((putbuf(&mem,c)) == (-1)) {
  245.                         writes("\007*** file receiption buffer overflow ***");
  246.                         inchan = FALSE;
  247.                         return(-1);
  248.                     }
  249.                 }
  250.             }
  251.             oldc = c;
  252.         }
  253.         return(c);
  254.     }
  255.  
  256.     /* no character found */
  257.     return(0);
  258. }
  259.  
  260. /*********************************************************************/
  261. /* write characters from the screen buffer to the screen.  Returns a */
  262. /* -1 if error occured, 0 if no characters in buffer, or character   */
  263. /* written.                                                          */
  264. /*                                                                   */
  265. int wrtscr()
  266. {
  267.     static char c;
  268.     static int i,iret;
  269.  
  270.     /* get character from screen buffer */
  271.     if ((iret = getbuf(&crt)) != (-1)) {
  272.         c = iret&127;    /* strip parity */
  273.  
  274.         /* if line feed then scroll screen */
  275.         if (c == '\n') {
  276.             if ((iret = doscr()) == (-1)) {
  277.                 return(-1);
  278.             }
  279.  
  280.         /* handle tabs seperatly */
  281.         } else if (c == '\t') {
  282.             if ((iret = dotab()) == (-1)) {
  283.                 return(-1);
  284.             }
  285.  
  286.         /* output other characters */
  287.         } else {
  288.             biostty(c);
  289.         }
  290.         return(c);
  291.     }
  292.  
  293.     /* no character in buffer */
  294.     return(0);
  295. }
  296.  
  297. /*********************************************************************/
  298. /* scroll the screen up one line at a time while checking the comm   */
  299. /* port for data receiption.  Returns a -1 if an error occured.      */
  300. /*                                                                   */
  301. int doscr()
  302. {
  303.     static char fillchar;
  304.     static int trow,tlcol,brow,brcol;
  305.     static int iret;
  306.  
  307.     /* initialize */
  308.     fillchar = 0x20;    /* fill opened line with blanks */
  309.     tlcol = 0;        /* top left column of window */
  310.     brcol = 79;        /* bottom right column of window */
  311.  
  312.     /* begin check and scroll loop */
  313.     for(trow=0;trow<24;trow++) {
  314.  
  315.         /* check comm port for data receiption */
  316.         if ((iret = readcomm()) == (-1)) {
  317.             return(-1);
  318.         }
  319.  
  320.         /* scroll 1 line up */
  321.         brow = trow + 1;
  322.         biosup(1,trow,tlcol,brow,brcol,fillchar);
  323.     }
  324.  
  325.     return(0);
  326. }
  327.  
  328. /*********************************************************************/
  329. /* Output a horizontal tab to screen while checking communications   */
  330. /* port for transmission.  Returns a -1 if an error occured.         */
  331. /*                                                                   */
  332. int dotab()
  333. {
  334.     static int iret,irow,icol;
  335.  
  336.     /* check comm port for receiption of data */
  337.     if ((iret = readcomm()) == (-1)) {
  338.         return(-1);
  339.     }
  340.  
  341.     /* find cursor position */
  342.     iret = biospos();
  343.     icol = iret & 255;    /* column returned in low order bits */
  344.     irow = iret >> 8;    /* row returned in high order bits */
  345.  
  346.     /* check comm port for receiption of data */
  347.     if ((iret = readcomm()) == (-1)) {
  348.         return(-1);
  349.     }
  350.  
  351.     /* calculate tab position */
  352.     icol++;
  353.     while ((icol % 8) != 0) {
  354.         icol++;
  355.     }
  356.  
  357.     /* set cursor to that position */
  358.     biosset(irow,icol);
  359.  
  360.     return(0);
  361. }
  362.  
  363. /*********************************************************************/
  364. /* write characters to communications port for transmission.  Return */
  365. /* a -1 if error, 0 if no characters written, or character written.  */
  366. /*                                                                   */
  367. int wrtcomm()
  368. {
  369.     static char c,pushback;
  370.     static int iret,lstat;
  371.  
  372.     /* write characters to communications port for transmission */
  373.     lstat=inp(lsr);
  374.     if (((lstat&32) != 0) && (!gotxoff)) {
  375.  
  376.         /* write characters received from keyboard */
  377.         if ((iret=getbuf(&com)) != (-1)) {
  378.             c = iret&127;
  379.             outp(thr,c);
  380.             if (lecho) putbuf(&crt,c);
  381.             return(c);
  382.  
  383.         /* write characters from file */
  384.         } else if (outchan) {
  385.             if (pushback != NULL) {
  386.                 outp(thr,pushback);
  387.                 pushback = NULL;
  388.                 if (lecho) putbuf(&crt,pushback);
  389.                 return(pushback);
  390.             }
  391.  
  392.             if ((iret=getbuf(&mem)) == (-1)) {
  393.                 outp(thr,CONZ);
  394.                 fclose(outchan);
  395.                 outchan = FALSE;
  396.                 mem.wbuf = mem.rbuf = mem.fbuf;
  397.                 return(0);
  398.             }
  399.  
  400.             c = iret&127;
  401.             if (c == '\n') {
  402.                 outp(thr,'\r');
  403.                 if (lecho) {
  404.                     putbuf(&crt,'\r');
  405.                     putbuf(&crt,'\n');
  406.                 } else {
  407.                     dowait();
  408.                 }
  409.             } else {
  410.                 outp(thr,c);
  411.                 if (lecho) putbuf(&crt,c);
  412.             }
  413.             return(c);
  414.         }
  415.     }
  416.  
  417.     return(0);
  418. }
  419.  
  420. /*********************************************************************/
  421. /* Function to wait until the receiption of a line feed after the    */
  422. /* transmission of a carriage return.                                */
  423. /*                                                                   */
  424. int dowait()
  425. {
  426.     int iret;
  427.  
  428.     /* loop */
  429.     while ((iret=readcomm()) != '\n') {
  430.         if (iret == -1) break;
  431.     }
  432.  
  433.     return(0);
  434. }
  435.  
  436. /*********************************************************************/
  437. /* Check the keyboard for receipt of a character and buffer it.      */
  438. /* Returns a -1 if error occured, 0 if no character at keyboard, or  */
  439. /* character typed.                                                  */
  440. /*                                                                   */
  441. /* kbhit() is a special IBM-PC microsoft "C" function.               */
  442. /*                                                                   */
  443. int readkey()
  444. {
  445.     static char c;
  446.  
  447.     /* check for keyboard entry */
  448.     if (kbhit()) {
  449.         c = readc();
  450.  
  451.         /* display menu if ESCAPE entered */
  452.         if (c == ESC) {
  453.             doesc();
  454.             return(c);
  455.         }
  456.  
  457.         /* character mapping */
  458.         if (c == '\b') {
  459.             c = DEL;
  460.         } else if (c == '\n') {
  461.             c = '\r';
  462.         }
  463.  
  464.         /* store character in keyboard buffer */
  465.         if (putbuf(&com,c) == (-1)) {
  466.             writes("\007");        /* buffer full */
  467.             return(-1);
  468.         }
  469.         return(c);
  470.     }
  471.  
  472.     return(0);
  473. }
  474.  
  475. /*********************************************************************/
  476. /* Write a character into a buffer.  Returns a -1 if overflow.       */
  477. /*                                                                   */
  478. int putbuf(p,c)
  479. struct buf *p;
  480. char c;
  481. {
  482.     *p->wbuf = c;
  483.  
  484.     /* increment (possible wrap-around) pointer */
  485.     if (++p->wbuf > p->lbuf) p->wbuf = p->fbuf;
  486.  
  487.     /* if overflow, indicate */
  488.     if (p->wbuf == p->rbuf) {
  489.         if (--p->wbuf < p->fbuf) p->wbuf = p->lbuf;
  490.         return(-1);
  491.     }
  492.  
  493.     return(0);
  494. }
  495.  
  496. /*********************************************************************/
  497. /* Read a character from a buffer.  Returns a -1 if buffer is empty. */
  498. /*                                                                   */
  499. int getbuf(p)
  500. struct buf *p;
  501. {
  502.     static int c;
  503.  
  504.     /* empty */
  505.     if (p->rbuf == p->wbuf) return(-1);
  506.  
  507.     /* get char, increment (possible wrap-around) pointer */
  508.     c = *p->rbuf;
  509.     if (++p->rbuf > p->lbuf) p->rbuf = p->fbuf;
  510.  
  511.     return(c);
  512. }
  513.  
  514. /*********************************************************************/
  515. /* Function to do special features.                                  */
  516. /*                                                                   */
  517. int doesc()
  518. {
  519.     char ans[3],memsiz[6];
  520.     char c;
  521.     int iret,ians;
  522.  
  523.     /* output special information */
  524.     loop:
  525.     escreen(2);        /* erase screen */
  526.  
  527.     writes("\r\n memory buffer is : ");
  528.     sprintf(memsiz,"%u",(mem.wbuf-mem.fbuf));
  529.     writes(memsiz);
  530.     writes("/");
  531.     sprintf(memsiz,"%u",(mem.lbuf-mem.fbuf));
  532.     writes(memsiz);
  533.  
  534.     writes("\r\n receive file is  : ");
  535.     writes((inchan)?infil:"<OFF>");
  536.  
  537.     writes("\r\n transmit file is : ");
  538.     writes((outchan)?outfil:"<OFF>");
  539.  
  540.     writes("\r\n local echo is    : ");
  541.     writes((lecho)?"<ON>":"<OFF>");
  542.  
  543.     /* output menu and accept choice */
  544.     if ((ians=chosit("comm",ans,sizeof(ans))) == (-1)) {
  545.         writes("\r\n\007*** error displaying menu ***");
  546.         ians = 4;
  547.     }
  548.  
  549.     /* execute command */
  550.     switch (ians) {
  551.  
  552.         case 5:
  553.             if (inchan) {
  554.                 wrtbuf();
  555.                 fclose(inchan);
  556.             }
  557.             if (outchan) fclose(outchan);
  558.             outp(mcr,0);    /* drop DTR and RTS */
  559.             writes("\r\n");
  560.             exit();
  561.             break;
  562.  
  563.         case 4:
  564.             cursor(25,1);
  565.             writes("\r\n*** you are now back as a terminal ***\r\n");
  566.             return(0);
  567.             break;
  568.  
  569.         case 3:
  570.             lecho = !lecho;
  571.             break;
  572.  
  573.         case 2:
  574.             if (outchan) {
  575.                 fclose(outchan);
  576.                 outchan = FALSE;
  577.                 mem.wbuf = mem.rbuf = mem.fbuf;
  578.             } else {
  579.                 if (inchan) {
  580.                     wrtbuf();
  581.                     fclose(inchan);
  582.                     inchan = FALSE;
  583.                 }
  584.                 sendfile:
  585.                 writes("\r\n\nFilename? ");
  586.                 reads(outfil,sizeof(outfil));
  587.                 if (outfil[0] == NULL) goto done;
  588.  
  589.                 if ((outchan=fopen(&outfil[0],"r")) == NULL) {
  590.                     writes("\007  *** can't open file ***");
  591.                     goto sendfile;
  592.                 }
  593.  
  594.                 readbuf();
  595.             }
  596.             break;
  597.  
  598.         case 1:
  599.             if (inchan) {
  600.                 wrtbuf();
  601.                 fclose(inchan);
  602.                 inchan = FALSE;
  603.             } else {
  604.                 if (outchan) {
  605.                     fclose(outchan);
  606.                     outchan = FALSE;
  607.                     mem.wbuf = mem.rbuf = mem.fbuf;
  608.                 }
  609.                 savefile:
  610.                 writes("\r\n\nFilename? ");
  611.                 reads(infil,sizeof(infil));
  612.                 if (infil[0] == NULL) goto done;
  613.  
  614.                 if ((inchan=fopen(&infil[0],"w")) == NULL) {
  615.                     writes("\007  *** can't open file ***");
  616.                     goto savefile;
  617.                 }
  618.             }
  619.             break;
  620.  
  621.     }
  622.     done:
  623.     goto loop;
  624. }
  625.  
  626. /*********************************************************************/
  627. /* Function to write the data receiption buffer to output file.      */
  628. /*                                                                   */
  629. int wrtbuf()
  630. {
  631.     for (mem.rbuf=mem.fbuf;mem.rbuf<mem.wbuf;mem.rbuf++) {
  632.         fputc(*mem.rbuf,inchan);
  633.     }
  634.  
  635.     mem.wbuf = mem.rbuf = mem.fbuf;
  636.     return(0);
  637. }
  638.  
  639. /*********************************************************************/
  640. /* Function to read a file into the file transmission buffer.        */
  641. /* Returns a 0 if successful, or a -1 if buffer overflow.            */
  642. /*                                                                   */
  643. int readbuf()
  644. {
  645.     static char c;
  646.     static int iret;
  647.  
  648.     /* loop until end-of-file is found */
  649.     while ((iret=getc(outchan)) != EOF) {
  650.         c = iret&127;
  651.         if ((putbuf(&mem,c)) == (-1)) {
  652.             writes("\r\n\007*** file transmission buffer overflow ***");
  653.             return(-1);
  654.         }
  655.     }
  656.  
  657.     return(0);
  658. }
  659.